#ifndef __MV_PLUGIN_INTERFACES
#define __MV_PLUGIN_INTERFACES

//---------------------------------------------------------------------------
#define MVP_HAS_CONFIG     0x00000001UL
#define MVP_IS_MAPSOURCE   0x00010000UL

enum MVM_Object {      // Ptr
  mvoMap,              // PMVMapInterface or NULL if map close
  mvoPosition,         // PMVConnection or NULL for main position
  mvoStartStop,        // PMVConnection or NULL for all connections
  mvoConnectionsList,
  mvoWaypointsList,
  mvoTracksList,
  mvoSelection,        // NULL
  mvoModule,           // PMVModule for module cfg, NULL for main cfg
  mvoToolbar,          // NULL
  mvoHotkeys,          // NULL
};

enum MVM_Changes {     // Ptr
  mvsChange,           // see MVM_Object Ptr descr
  mvsChangeItem        // List item
};

LOCALSTRUCTBASE( MVModule, public HLibPackageInfo )
  DWORD       Version;      //MV_MAIN_VERION
  DWORD       Flags;        //MVP_xxx

  //Base
  virtual void          GV_DECLSPEC Initialize( PMVMainInfo Info ) = 0;
  virtual void          GV_DECLSPEC Shutdown( void ) = 0;
  virtual void          GV_DECLSPEC Configure( TForm *Parent ) = 0;
  virtual PMVMapSource  GV_DECLSPEC GetMapSource( void ) = 0;
  virtual void          GV_DECLSPEC FirstLoad( void ) = 0;

  //Changes
  virtual bool          GV_DECLSPEC SaveChanges( bool AskForSave ) = 0;
  virtual bool          GV_DECLSPEC IsChanged( void ) = 0;

  //Notify
  virtual void          GV_DECLSPEC RefreshInterface( void ) = 0;
  virtual void          GV_DECLSPEC ControlDestroy( PGUIControlInfo p, TControl *ctl ) = 0;
  virtual void          GV_DECLSPEC ProcessCommandLine( void ) = 0;
  virtual void          GV_DECLSPEC NotifyChanges( MVM_Object obj, MVM_Changes ch, LPVOID ptr ) = 0;

  //Paint
  virtual void          GV_DECLSPEC Paint( TCanvas *dc, const MyRect& r ) = 0;
  virtual void          GV_DECLSPEC PaintOnMap( TCanvas *dc, const MyRect& r ) = 0;
};

//---------------------------------------------------------------------------
/* Menu items Tag ids.
*/
#define ID_MENUS_START            1000   //Plugin menu items
#define ID_MENU_CHECKER_START     5000   //Items set with HMenuItemEvent

/* Main menu item names.
*/
#define MAIN_MENU          "MainMenu"
#define MENU_FILES         "mnuFiles"
#define MENU_EDIT          "mnuEdit"
#define MENU_VIEW          "mnuView"
#define MENU_TOOLS         "mnuTools"
#define MENU_LOAD          "mnuLoad"
#define MENU_SAVE          "mnuSave"
#define MENU_CLEAR         "mnuClear"

/* Main config parameters.
*/
#define OPT_NAME_TBCAPHEIGHT     "Defaults/ToolbarCaptionHeight"     // int
#define OPT_DEF_TBCAPHEIGHT     16

/* Windows messages used by modules
*/
#define MVM_ID_START        (WM_USER+1000)

typedef TCustomToolWindow97 MVToolWindow, *PMVToolWindow;

LOCALSTRUCT( MVKeyInfo )
  DWORD         Id;
  PathString    Caption;
  TImageList   *Images;
  int           ImageIndex;
  TNotifyEvent  OnExecute;
  TAction      *Action;
};

LOCALSTRUCT( MVConnectionInfo )
  int               Index;      //Index in main connections array
  bool              Enabled,    //true if source enabled
                    IsMain,     //true if source selected as main source
                    IsRun;      //true if source is run
  PathString        Name;       //Name
  PMVDataHandler    Handler;    //OPT handler
  PMVPositionSource Source;     //OPT source
  GPosition         Position;   //Current position (valid if run)
};

typedef TShortCut MVHotkey;
#define MV_KEY_SHIFT              scShift
#define MV_KEY_CTRL               scCtrl
#define MV_KEY_ALT                scAlt
#define MV_MK_KEY( sh, k )        ((MVHotkey)(sh|((WORD)k)))
#define KeyShift2Hotkey( k, sh )  ShortCut( k, sh )
#define ShortCut2Hotkey( sc )     sc
#define Hotkey2Str( hk )          ShortCutToText(hk).c_str()
#define Hotkey2ShortCut( hk )     hk

enum MVWC_Options {       //Param          Accessibility
  mvwcCaptionMenu,        // TPopupMenu*   RW
  mvwcCaptionVisible,     // bool          RW
  mvwcDoubleBuffered,     // bool          RW
  mvwcMoveControl,        // TControl*     RW
  mvwcConfig,             // PHConfigItem  R
  mvwcControlForm,        // PTForm        R
  mvwcCaption,            // AnsiString    RW
};

LOCALSTRUCT( MVWindowHandler )
  virtual bool SetOption( MVWC_Options op, LPCVOID param ) = 0;
  virtual bool GetOption( MVWC_Options op, LPVOID param ) = 0;
};

LOCALSTRUCT( MVMainInfo )
  DWORD Version;      //MV_MAIN_VERION

  void                (GV_DECLSPEC *LoadMap)( PMVMapInterface intf );
  PTForm              (GV_DECLSPEC *MainForm)( void );
  void                (GV_DECLSPEC *PrepareMenu)( TMenuItem* mi );

  bool                (GV_DECLSPEC *RegisterControl)( const GUIControlInfo& p );
  void                (GV_DECLSPEC *UnregisterControl)( DWORD id );
  int                 (GV_DECLSPEC *GetNextToolbarIndex)( void );
  void                (GV_DECLSPEC *SaveToolbar)( PHConfigItem cfg, TCustomToolWindow97 *tb );
  void                (GV_DECLSPEC *LoadToolbar)( PHConfigItem cfg, TCustomToolWindow97 *tb );

  void                (GV_DECLSPEC *KillFocus)( void );
  int                 (GV_DECLSPEC *ScreenW)( void );
  int                 (GV_DECLSPEC *ScreenH)( void );
  void                (GV_DECLSPEC *Invalidate)( void );

  PMVMapInterface     (GV_DECLSPEC *GetMap)( void );

  void                (GV_DECLSPEC *GetPosition)( GPosition& p );
  void                (GV_DECLSPEC *SetPosition)( const GPosition& p );
  bool                (GV_DECLSPEC *GetConnectionInfo)( int idx /*-1, 0...*/, MVConnectionInfo& ci );

  int                 (GV_DECLSPEC *Zoom)( int Zoom /*=-1*/ );
  void                (GV_DECLSPEC *ScrollTo)( GCoord_t x, GCoord_t y );
  void                (GV_DECLSPEC *SetScrollBars)( int hMin, int hMax, int hPos /*=-1*/,
                                                    int vMin, int vMxx, int vPos /*=-1*/ );

  int                 (GV_DECLSPEC *ModulesCount)( void );
  PMVModule           (GV_DECLSPEC *GetModule)( int idx );
  PMVModule           (GV_DECLSPEC *FindModule)( CONSTSTR nm );

  DWORD               (GV_DECLSPEC *RegisterMapLoader)( PMVMapLoader p, CONSTSTR nm, CONSTSTR FilterStr );
  void                (GV_DECLSPEC *UnregisterMapLoader)( DWORD id );

  int                 (GV_DECLSPEC *Datum)( int dt /*=-1*/ );
  degTypes            (GV_DECLSPEC *DegType)( degTypes dt /*=dtMAX*/ );
  Coordinate_Type     (GV_DECLSPEC *CoordSys)( Coordinate_Type cs /*=CoordSUnknown*/ );

  DWORD               (GV_DECLSPEC *RegisterDataHandler)( PMVModule m, const MVHandleInfo& p );
  void                (GV_DECLSPEC *UnregisterDataHandler)( DWORD id );

  DWORD               (GV_DECLSPEC *RegisterDataSource)( PMVModule m, const MVPositionInfo& p );
  void                (GV_DECLSPEC *UnregisterDataSource)( DWORD id );

  void                (GV_DECLSPEC *RegisterKeyAction)( PMVKeyInfo p );
  void                (GV_DECLSPEC *UnregisterKeyAction)( DWORD id );
  void                (GV_DECLSPEC *AddKeyAction)( DWORD id, MVHotkey hotkey );

  PTForm              (GV_DECLSPEC *RegisterWindow)( PTForm frm, CONSTSTR nm, DWORD id );
  PTForm              (GV_DECLSPEC *LocateWindowByName)( CONSTSTR nm );
  PTForm              (GV_DECLSPEC *LocateWindowById)( DWORD id );
  void                (GV_DECLSPEC *UnregisterWindow)( PTForm frm );
  PMVWindowHandler    (GV_DECLSPEC *GetWindowHandler)( PTForm frm );
};

/* ---------------------------------------------------------------------------
   HELPERS
     MVModuleForm - template to quick access to registered windows
   --------------------------------------------------------------------------- */
template <class T> class MVModuleForm {
    CONSTSTR         Name;
    PMVMainInfo      MainInfo;

    bool GetHandler( void ) {
      Handler = NULL;
      PTForm f = Locate();
      if ( !f )
        return false;
      Handler = MainInfo->GetWindowHandler(f);
      return Handler != NULL;
    }

  public:
    PMVWindowHandler Handler;

  public:
    MVModuleForm( PMVMainInfo mi, CONSTSTR nm ) { MainInfo = mi; Name = nm; GetHandler(); }

    PTForm  Locate( void )      { return MainInfo->LocateWindowByName(Name); }
    PTForm  Register( void )    { return MainInfo->RegisterWindow( new T(NULL), Name, 0 ); }
    void    Unregister( void )  { return MainInfo->UnregisterWindow( Locate() ); }

    T*      CF( void )          { PTForm frm; return (Handler && Handler->GetOption(mvwcControlForm,&frm)) ? dynamic_cast<T*>(frm) : NULL; }
    T*      operator->()        { return CF(); }

#define D( tp, nm, def )   tp Get##nm( void ) { if ( !GetHandler() ) return def; tp p; return Handler->GetOption(mvwc##nm,&p) ? p : def; } \
                           void Set##nm( tp val ) { if ( GetHandler() ) Handler->SetOption(mvwc##nm,&val); }
    D( TPopupMenu*,  CaptionMenu,    NULL )
    D( bool,         CaptionVisible, true )
    D( bool,         DoubleBuffered, false )
    D( TControl*,    MoveControl,    NULL )
    D( PHConfigItem, Config,         NULL )
    D( T*,           ControlForm,    NULL )
    D( AnsiString,   Caption,        "" )
#undef D
};

#endif